/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.channel;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.AttributeMap;

import java.net.InetSocketAddress;
import java.net.SocketAddress;


/**
 * 同网络 socket 或能进行 I/O 操作(如, read, write, connect, bind)的组件的联系.
 * <p>
 * channel 为用户提供:
 * <ul>
 * <li>当前 channel 的状态(open? connected?)</li>
 * <li>channel 的 {@linkplain ChannelConfig 配置参数}(如 receive buffer 大小)</li>
 * <li>channel 支持的 I/O 操作(e.g. read, write, connect, and bind)</li>
 * <li>跟此 channel 相关的, 处理所有 I/O 事件和请求的 {@link ChannelPipeline}</li>
 * </ul>
 *
 * <h3>所有的 I/O 操作均是异步的.</h3>
 * <p>
 * Netty 中所有 I/O 操作均是异步的.
 * 这意味着, 任意 I/O 调用将立即返回, 并且不保证在本次调用结束时, 请求的 I/O 操作已经完成.
 * 相反, 将返回给您一个 {@link ChannelFuture} 实例, 当请求的 I/O 操作已经成功, 失败或取消时, 它将通知您.
 *
 * <h3>Channel 是有层级结构的</h3>
 * <p>
 * {@link Channel} 可以有一个 {@linkplain #parent() parent}(具体取决于它如何被创建).
 * 例如, {@link SocketChannel}, 由 {@link ServerSocketChannel} 接受, 将把 {@link ServerSocketChannel}
 * 作为 parent 并作为 {@link #parent()} 的返回值.
 * <p>
 * 层级结构的语义取决于 {@link Channel} 所属 transport 的实现.
 * 例如, 您可以编写新的 {@link Channel} 实现, 它可以创建共享一个 socket 连接的 sub-channel,
 * 就像 <a href="http://beepcore.org/">BEEP</a> 和 <a href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a> 那样.
 *
 * <h3>向下强制类型转换(Downcast)以访问 transport 特定的操作</h3>
 * <p>
 * 某些 transport 暴露特定于它的额外操作. 将 {@link Channel} 强制转换为子类以调用这些操作.
 * 例如, 对于老的 I/O datagram transport, {@link DatagramChannel} 提供了 multicast join / leave 操作.
 *
 * <h3>释放资源</h3>
 * <p>
 * 一旦操作完 {@link Channel}, 调用 {@link #close()} or {@link #close(ChannelPromise)} 以释放所有资源是很重要的.
 * 这确保了所有资源都将以恰当的方式被释放, 如 filehandles.
 */
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {

    /**
     * 返回该 {@link Channel} 全局唯一标识符
     */
    ChannelId id();

    /**
     * 返回该 {@link Channel} 注册到的 {@link EventLoop}.
     */
    EventLoop eventLoop();

    /**
     * 返回该 {@link Channel} 的 parent.
     *
     * @return the parent channel. 如果没有, 返回 {@code null}.
     */
    Channel parent();

    /**
     * 返回该 {@link Channel} 的配置
     */
    ChannelConfig config();

    /**
     * 如果 {@link Channel} 是 open 并且可能稍后被激活, 返回 {@code true}
     */
    boolean isOpen();

    /**
     * 如果该 {@link Channel} 已向某个 {@link EventLoop} 注册, 则返回 {@code true}.
     */
    boolean isRegistered();

    /**
     * 如果该 {@link Channel} 处于活动状态并已连接, 则返回{@code true}.
     */
    boolean isActive();

    /**
     * 返回该 {@link Channel} 的 {@link ChannelMetadata}, 它描述了该 {@link Channel} 的性质.
     */
    ChannelMetadata metadata();

    /**
     * 返回该 channel 绑定的本地地址
     * <p>
     * 返回的 {@link SocketAddress} 应被向下转型为更具体的类型, 如 {@link InetSocketAddress}, 以获取详细信息.
     *
     * @return 该 channel 的 local address; 如果未绑定, 返回 {@code null}.
     */
    SocketAddress localAddress();

    /**
     * 返回该 channel 连接的远程地址
     * <p>
     * 返回的 {@link SocketAddress} 应被向下转型为更具体的类型, 如 {@link InetSocketAddress}, 以获取详细信息.
     *
     * @return 该 channel 的 local address; 如果未连接, 返回 {@code null}.
     * 如果该 channel 未连接, 但是它可以接收来自任意远程地址的信息, 如 {@link DatagramChannel},
     * 使用 {@link DatagramPacket#recipient()} 来确定接收到的消息的来源, 因为本方法将返回 {@code null}.
     */
    SocketAddress remoteAddress();

    /**
     * 返回当该 channel 被关闭时, 将会被通知的 {@link ChannelFuture}.
     * <p>
     * 该方法永远返回相同的 future 实例.
     */
    ChannelFuture closeFuture();

    /**
     * 当且仅当 I/O 线程将立刻执行请求的写操作时返回 {@code true}.
     * 当该方法返回 {@code false} 时, 任意写请求都将排队, 直至 I/O 线程准备好处理队列中的写请求.
     */
    boolean isWritable();

    /**
     * 直至 {@link #isWritable()} 返回 {@code false}, 可被写的字节数.
     * <p>
     * 该数值永远为非负数. 如果 {@link #isWritable()} 为 {@code false}, 该值为 0.
     */
    long bytesBeforeUnwritable();

    /**
     * 直至 {@link #isWritable()} 返回 {@code true}, 底层 buffer 需要耗尽的字节数.
     * <p>
     * 该数值永远为非负数. 如果 {@link #isWritable()} 为 {@code true}, 该值为 0.
     */
    long bytesBeforeWritable();

    /**
     * 返回提供不安全操作的仅供内部使用的对象.
     */
    Unsafe unsafe();

    /**
     * Return the assigned {@link ChannelPipeline}.
     */
    ChannelPipeline pipeline();

    /**
     * 返回分配的 {@link ByteBufAllocator}， 它将被用于分配  {@link ByteBuf}
     */
    ByteBufAllocator alloc();

    @Override
    Channel read();

    @Override
    Channel flush();

    /**
     * 不应该从用户代码中调用的不安全操作.
     * <p>
     * 提供这些方法仅用来实现实际的 transport, 并且必须从 I/O 线程调用这些方法, 除了以下方法:
     * <ul>
     *   <li>{@link #localAddress()}</li>
     *   <li>{@link #remoteAddress()}</li>
     *   <li>{@link #closeForcibly()}</li>
     *   <li>{@link #register(EventLoop, ChannelPromise)}</li>
     *   <li>{@link #deregister(ChannelPromise)}</li>
     *   <li>{@link #voidPromise()}</li>
     * </ul>
     */
    interface Unsafe {

        /**
         * 返回分配的 {@link RecvByteBufAllocator.Handle}, 在接收数据时, 它将被用于分配 {@link ByteBuf}
         */
        RecvByteBufAllocator.Handle recvBufAllocHandle();

        /**
         * 返回绑定到 local 的 {@link SocketAddress}; 如果没有, 返回 {@code null}.
         */
        SocketAddress localAddress();

        /**
         * 返回绑定到 remote 的 {@link SocketAddress}; 如果没有, 返回 {@code null}.
         */
        SocketAddress remoteAddress();

        /**
         * Register the {@link Channel} of the {@link ChannelPromise} and notify
         * the {@link ChannelFuture} once the registration was complete.
         */
        void register(EventLoop eventLoop, ChannelPromise promise);

        /**
         * Bind the {@link SocketAddress} to the {@link Channel} of the {@link ChannelPromise} and notify
         * it once its done.
         */
        void bind(SocketAddress localAddress, ChannelPromise promise);

        /**
         * Connect the {@link Channel} of the given {@link ChannelFuture} with the given remote {@link SocketAddress}.
         * If a specific local {@link SocketAddress} should be used it need to be given as argument. Otherwise just
         * pass {@code null} to it.
         * <p>
         * The {@link ChannelPromise} will get notified once the connect operation was complete.
         */
        void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);

        /**
         * Disconnect the {@link Channel} of the {@link ChannelFuture} and notify the {@link ChannelPromise} once the
         * operation was complete.
         */
        void disconnect(ChannelPromise promise);

        /**
         * Close the {@link Channel} of the {@link ChannelPromise} and notify the {@link ChannelPromise} once the
         * operation was complete.
         */
        void close(ChannelPromise promise);

        /**
         * 立刻关闭该 {@link Channel} 而不触发任何事件.
         * <p>
         * 可能只在当注册尝试失败时才有用.
         */
        void closeForcibly();

        /**
         * Deregister the {@link Channel} of the {@link ChannelPromise} from {@link EventLoop} and notify the
         * {@link ChannelPromise} once the operation was complete.
         */
        void deregister(ChannelPromise promise);

        /**
         * Schedules a read operation that fills the inbound buffer of the first {@link ChannelInboundHandler} in the
         * {@link ChannelPipeline}.  If there's already a pending read operation, this method does nothing.
         */
        void beginRead();

        /**
         * Schedules a write operation.
         */
        void write(Object msg, ChannelPromise promise);

        /**
         * Flush out all write operations scheduled via {@link #write(Object, ChannelPromise)}.
         */
        void flush();

        /**
         * Return a special ChannelPromise which can be reused and passed to the operations in {@link Unsafe}.
         * It will never be notified of a success or error and so is only a placeholder for operations
         * that take a {@link ChannelPromise} as argument but for which you not want to get notified.
         */
        ChannelPromise voidPromise();

        /**
         * Returns the {@link ChannelOutboundBuffer} of the {@link Channel} where the pending write requests are stored.
         */
        ChannelOutboundBuffer outboundBuffer();
    }
}
